package com.xuanyue.db.xuan.core.index;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.xuanyue.db.xuan.core.exception.SQLException;
import com.xuanyue.db.xuan.core.table.IBitIndex;
import com.xuanyue.db.xuan.core.table.IColumn;
import com.xuanyue.db.xuan.core.table.ISortElement;
import com.xuanyue.db.xuan.core.table.expr.Expr;
import com.xuanyue.db.xuan.core.table.expr.ExprValue;
import com.xuanyue.db.xuan.core.table.expr.ExprValueType;
import com.xuanyue.db.xuan.core.table.expr.SortTemplate;
import com.xuanyue.db.xuan.msg.VLAUETYPE;

public class KeyIndex implements IColumn{

	protected Map<Integer,XGHKeySplit> splits = new HashMap<>();
	private String path;
	
	@Override
	public boolean modify(IColumn newOne,boolean cpDataFromOld) {
		return false;
	}
	
	@Override
	public void setPath(String path) {
		this.path = path;
	}
	@Override
	public void init() {
		File pa = new File(path);
		pa.mkdirs();
	}
	@Override
	public void save() {
		for(Entry<Integer,XGHKeySplit> en:splits.entrySet()) {
			RandomAccessFile rw = null;//new RandomAccessFile(String.format("%s/splits/%s", path,i),"rw");
			try {
				rw = new RandomAccessFile(String.format("%s/%s", path,en.getKey()),"rw");
				int[] data = en.getValue().getDate();
				int s = data.length;
				for(int i=0;i<s;) {
					rw.writeInt(data[i++]);
				}
			}catch (Exception e) {
				throw new SQLException(e);
			}finally {
				if(rw!=null) {
					try {
						rw.close();
					} catch (IOException e) {
						throw new SQLException(e);
					}
				}
			}
		}
	}

	@Override
	public void load(){
		File pa = new File(path);
		XGHKeySplit split = null;
		for(File f:pa.listFiles()) {
			split = new XGHKeySplit();
			RandomAccessFile rw = null;//new RandomAccessFile(String.format("%s/splits/%s", path,i),"rw");
			try {
				rw = new RandomAccessFile(f,"r");
				int[] data = split.getDate();
				for(int i=0,s=data.length;i<s;) {
					data[i++]=rw.readInt();
				}
				splits.put(Integer.parseInt( f.getName() ), split);
			}catch (Exception e) {
				throw new SQLException(e);
			}finally {
				if(rw!=null) {
					try {
						rw.close();
					} catch (IOException e) {
						throw new SQLException(e);
					}
				}
			}
		}
		
	}

	@Override
	public void set(int rowId, ExprValue value) {
		
		if(!ExprValueType.INT.is(value.getType())) {
			throw new SQLException("type ERROR : the value  type mask be int in KeyIndex");
		}
		
		int spl = rowId/XGHBitSet.SET_SIZE;
		XGHKeySplit split = splits.get(spl);
		if(split==null) {
			synchronized (this) {
				split = splits.get(spl);
				if(split==null) {
					split = new XGHKeySplit();
					splits.put(spl, split);
				}
			}
		}
		int v = value.getValue();
		split.set(rowId%XGHBitSet.SET_SIZE, v);
	}

	@Override
	public void saveRow(int rowId) {
		int spl = rowId/XGHBitSet.SET_SIZE;
		XGHKeySplit split = splits.get(spl);
		if(split!=null) {
			RandomAccessFile rw = null;//new RandomAccessFile(String.format("%s/splits/%s", path,i),"rw");
			try {
				rw = new RandomAccessFile(String.format("%s/%s", path,spl),"rws");
				rw.seek( (rowId%XGHBitSet.SET_SIZE)*4  );
				rw.writeInt(split.get(rowId));
			} catch (Exception e) {
				throw new SQLException(e);
			}finally {
				if(rw!=null) {
					try {
						rw.close();
					} catch (IOException e) {
						throw new SQLException(e);
					}
				}
			}
		}
		
	}

	public void mapTo(IBitIndex me,IBitIndex tar) {
		for (int j = me.nextSetBit(0); j >= 0; j = me.nextSetBit(j+1)) {
			tar.set( get(j));
		}
	}
	
	@Override
	public Integer get(int rowId) {
		int spl = rowId/XGHBitSet.SET_SIZE;
		XGHKeySplit split = splits.get(spl);
		if(split!=null) {
			return split.get(rowId);
		}
		return -1;
	}
	@Override
	public ExprValue getExprValue(int rowId) {
		return new ExprValue(ExprValueType.INT, get(rowId));
	}

	@Override
	public boolean checkType(ExprValue v) {
		return ExprValueType.INT.is(v.getType())||ExprValueType.NULL.is(v.getType());
	}

	@Override
	public void flush(int maxId) {
	}

	@Override
	public int getDataSize() {
		return 32;
	}

	@Override
	public List<ISortElement> getSortE(SortTemplate sortTemplate) {
		return null;
	}

	@Override
	public boolean checkSortE(SortTemplate sortTemplate) {
		return false;
	}

	@Override
	public VLAUETYPE getType() {
		return null;
	}
	@Override
	public void exe(Expr expr, List<IBitIndex> caches) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public int checkAndContSource(Expr expr) {
		// TODO Auto-generated method stub
		return 0;
	}

	


}
class XGHKeySplit{
	private int[] data = new int[XGHBitSet.SET_SIZE];
	public XGHKeySplit() {
		for(int i=0,s=data.length;i<s;) {
			data[i++]=-1;
		}
	}
	public void set(int index,int value) {
		data[index%XGHBitSet.SET_SIZE]=value;
	}
	public int get(int index) {
		return data[index%XGHBitSet.SET_SIZE];
	}
	int[] getDate() {
		return data;
	}
}
